/*
 * @Author: b_cheng 2276306147@qq.com
 * @Date: 2024-06-22 13:33:26
 * @LastEditors: b_cheng 2276306147@qq.com
 * @LastEditTime: 2024-06-22 15:02:49
 * @FilePath: \新手入门\rune_simulation.cpp
 * @Description: 能量机关模拟器，
 * 
 * Copyright (c) 2024 by 朱云飞 , All Rights Reserved. 
 */

#include <opencv2/opencv.hpp>
#include <iostream>
#include <random>
#include <math.h>
#include <chrono>

#define PI acos(-1)
#define RUNE_WIDTH 1024
#define RUNE_HEIGHT 512
#define RUN_DELAY 1
#define SCALE_X 5 
#define SCALE_Y 4


double rune_delta_radian,rune_init_radian,rune_current_radian;
int rune_init_clock = 1;  
bool rune_init_isbig = true;
cv::Point2d rune_raw_point,rune_raw_noise,rune_noised_point;
double rune_raw_velocity,rune_raw_sumvelocity,rune_raw_scalevelocity;
std::vector<double> rune_data;

double SetDradian(const int& rune_clock,const bool& rune_isbig,const long& millisec){
    double rune_dradian = 0.0f;
    if(rune_isbig){
        // printf("big");
        //a:0.780~1.045   w:1.884~2.000   b:b=2.090-a
        std::uniform_real_distribution<double> u_a(0.780,1.045);
        std::default_random_engine rune_uinit_a(time(0));
        static double rune_big_a= u_a(rune_uinit_a);
        std::uniform_real_distribution<double> u_w(1.884,2.000);
        std::default_random_engine rune_uinit_w(time(0));
        static double rune_big_w= u_w(rune_uinit_w);
        static double rune_big_b = 2.090 - rune_big_a;
        rune_dradian = RUN_DELAY*0.001f * (rune_big_a * sin(rune_big_w * (millisec/1000+0.001*(millisec%1000))) + rune_big_b);
        std::cout<<"big_v:"<<rune_dradian<<std::endl;
    }else{
        //10RPM  de=10*2*PI/60*0.001
        // printf("small");
        rune_dradian = RUN_DELAY*0.001f*10*2*PI/60;
        // std::cout<<"small_v:"<<rune_dradian<<std::endl;
    }
    return (rune_clock>0) ? rune_dradian : -rune_dradian;
}

int main()
{
    cv::Mat img = cv::Mat::zeros(RUNE_HEIGHT,RUNE_WIDTH,CV_8UC3);
    img = cv::Scalar(255, 255, 255);
    cv::line(img, cv::Point(0, 0.5*RUNE_HEIGHT), cv::Point(0.70*RUNE_WIDTH, 0.5*RUNE_HEIGHT), cv::Scalar(0, 0, 0), 1);
    cv::circle(img, cv::Point(0.85*RUNE_WIDTH, 0.5*RUNE_HEIGHT), 0.25*RUNE_HEIGHT, cv::Scalar(0, 0, 0),1);
    cv::circle(img, cv::Point(0.85*RUNE_WIDTH, 0.5*RUNE_HEIGHT), 3, cv::Scalar(0, 0, 0),-1);
    cv::putText(img, "Rune Simulation", cv::Point(0.5*RUNE_WIDTH, 0.1*RUNE_HEIGHT), cv::FONT_HERSHEY_COMPLEX, 1.0, cv::Scalar(255, 0, 255));

    //随机种子刷新初始点弧度
    std::uniform_real_distribution<double> u_r(0,2*PI);//随机数分布类//范围是[0,9]
    std::default_random_engine rune_uinit_radian(time(0));
    rune_init_radian = u_r(rune_uinit_radian);
    std::cout<<rune_init_radian<<std::endl;
    //随机种子刷新旋转方向
    std::uniform_int_distribution<int> u_c(0,1);//随机数分布类//范围是[0,9]
    std::default_random_engine rune_uinit_clock(time(0));
    rune_init_clock = u_c(rune_uinit_clock);

    std::cout<<rune_init_clock<<std::endl;
    // rune_init_clock=0;//逆时针
    rune_current_radian += rune_init_radian;
    cv::Mat temp_img; // 创建临时图像副本
    // 将原始图像拷贝到临时图像副本
    temp_img = img.clone();
    std::default_random_engine generator(time(0));
    while(1)
    {
        auto millisec_since_epoch =std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
        std::cout<<"now:"<<millisec_since_epoch<<std::endl;

        //设置旋转弧度增量
        rune_delta_radian = SetDradian(rune_init_clock,rune_init_isbig,millisec_since_epoch);
        rune_current_radian += rune_delta_radian;
        
        //按照弧度公式刷新点
        rune_raw_point = cv::Point2d(0.25*RUNE_HEIGHT*cos(rune_current_radian)+0.85*RUNE_WIDTH,
            0.25*RUNE_HEIGHT*sin(rune_current_radian)+0.5*RUNE_HEIGHT);
        
        //添加噪声
        std::normal_distribution<double> normal_distribution(0, 0.1); // 平均值为0，标准差为0.1的正态分布
        rune_raw_noise = cv::Point2d(normal_distribution(generator),normal_distribution(generator)); // 生成正态分布的随机噪声
        // rune_raw_noise = cv::Point2d(0,0);
        rune_noised_point = rune_raw_point + rune_raw_noise; // 将正态分布噪声添加到rune_init_radian中
        // std::cout<<"rune_raw_point:"<<rune_raw_point<<std::endl;
        // std::cout<<"rune_raw_noise:"<<rune_raw_noise<<std::endl;
        // std::cout<<"rune_noised_point:"<<rune_noised_point<<std::endl;

        cv::circle(temp_img, cv::Point(rune_noised_point.x, rune_noised_point.y), 3, cv::Scalar(255, 0, 0),-1);
        cv::line(temp_img, cv::Point(0.85*RUNE_WIDTH, 0.5*RUNE_HEIGHT), cv::Point(rune_noised_point.x, rune_noised_point.y), cv::Scalar(255, 0, 0), 1);
        
        //解析速度
        static cv::Point2d rune_raw_lastpoint=rune_noised_point;
        //A为旧点，B为新点，C为圆心 //cv::Point(0.85*RUNE_WIDTH, 0.5*RUNE_HEIGHT)
        double len_a = sqrt(pow(rune_noised_point.x-0.85*RUNE_WIDTH,2)+pow(rune_noised_point.y-0.5*RUNE_HEIGHT,2));
        double len_b = sqrt(pow(rune_raw_lastpoint.x-0.85*RUNE_WIDTH,2)+pow(rune_raw_lastpoint.y-0.5*RUNE_HEIGHT,2));
        double len_c = sqrt(pow(rune_noised_point.x-rune_raw_lastpoint.x,2)+pow(rune_noised_point.y-rune_raw_lastpoint.y,2));
        rune_raw_velocity = acos((len_a*len_a+len_b*len_b-len_c*len_c)/(2*len_a*len_b))/RUN_DELAY;
        
        ((rune_noised_point.x-0.85*RUNE_WIDTH)*(rune_raw_lastpoint.y-0.5*RUNE_HEIGHT)-
            (rune_noised_point.y-0.5*RUNE_HEIGHT)*(rune_raw_lastpoint.x-0.85*RUNE_WIDTH)>0)?rune_raw_velocity*=-1:rune_raw_velocity*=1;

        rune_raw_lastpoint = rune_noised_point;

        std::cout<<"debug_rune_raw_velocity:"<<rune_raw_velocity<<std::endl;
        // 如果数据超过了最大长度，舍弃最早的数据
        if (rune_data.size() >= 0.70*RUNE_WIDTH) {
            rune_data.erase(rune_data.begin()); // 删除最早的数据
        }

        static int scale_i =0;
        rune_raw_sumvelocity += rune_raw_velocity;
        scale_i++;
        if(scale_i==SCALE_X ) {
            rune_raw_scalevelocity = rune_raw_sumvelocity/SCALE_X;
            //添加刷新曲线|自定义缩放
            static double rune_y_max=0,rune_y_min=0,rune_factor_scale=0;
            if(rune_raw_scalevelocity>0&&rune_y_max<rune_raw_scalevelocity)
            {
                rune_y_max=rune_raw_scalevelocity;
                if(rune_y_max>=0.01) rune_y_max=0.01f;
            }
            if(rune_raw_scalevelocity<0&&rune_y_min>rune_raw_scalevelocity)
            {
                rune_y_min=rune_raw_scalevelocity;
                if(rune_y_min<=-0.01) rune_y_min=-0.01f;
            }
            std::cout<<"rune_y_max:"<<rune_y_max<<","<<"rune_y_min:"<<rune_y_min<<std::endl;
            if(fabs(rune_y_max)>fabs(rune_y_min))
                rune_factor_scale=0.4*RUNE_HEIGHT/rune_y_max;
            else
                rune_factor_scale=0.4*RUNE_HEIGHT/fabs(rune_y_min);
            std::cout<<"rune_factor_scale:"<<rune_factor_scale<<std::endl;
            rune_data.push_back(rune_factor_scale*rune_raw_scalevelocity);
            std::cout<<"rune_raw_scalevelocity:"<<rune_raw_scalevelocity<<std::endl;
            rune_raw_sumvelocity = 0;
            scale_i=0;
        }

        
        std::cout<<"bufg:"<<std::endl;
        if(rune_data.size()){
            for(std::vector<double>::iterator it=rune_data.begin();it!=rune_data.end()-1;it++)
            {
                static int i=0;
                if(it==rune_data.begin()) i=0;
                // std::cout<<"point1:"<<cv::Point(i,*it)<<std::endl;
                // std::cout<<"point2:"<<cv::Point((i+1),*(it+1))<<std::endl;
                cv::line(temp_img, cv::Point(i,*it+0.5*RUNE_HEIGHT), cv::Point(++i,*(it+1)+0.5*RUNE_HEIGHT), cv::Scalar(255, 0, 0), 1);
            }
        }
        //添加时间间隔

        cv::imshow("temp_img", temp_img);
        cv::waitKey(RUN_DELAY);
        // 将临时图像副本叠加到原始图像上
        img.copyTo(temp_img);
    }

    cv::destroyAllWindows();
    return 0;
}